﻿using System;
using System.Reflection;
using System.Threading.Tasks;
using AspectCore.DynamicProxy;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NetMicro.Core.Extensions;
using NetMicro.HttpClient.Extensions;
using NetMicro.HttpClient.Internal;

namespace NetMicro.HttpClient.AspectExtend
{
    /// <summary>
    /// http请求拦截
    /// </summary>
    public class HttpProxy : IInterceptor
    {

        /// <summary>
        /// 
        /// </summary>
        public bool AllowMultiple { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public bool Inherited { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public int Order { get; set; }


        /// <summary>
        /// 动态拦截
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task Invoke(AspectContext context, AspectDelegate next)
        {
            try
            {
                HttpClientPart httpclientPart = context.ServiceMethod.BuildHttpClientPart(context.Parameters);
                if (context.ServiceMethod.ReturnType.GetTypeInfo().IsTask())
                {
                    await httpclientPart.SendAsync();
                    context.ReturnValue = Task.CompletedTask;
                    return;
                }
                if (context.ServiceMethod.ReturnType.IsVoid())
                {
                    await httpclientPart.SendAsync();
                    return;
                }


                MethodInfo methodInfo = typeof(HttpClientPart).GetMethod("SendAsAsync", BindingFlags.Instance | BindingFlags.Public);
                if (!context.ServiceMethod.IsAsync())
                {
                    Type resultTypeSync = context.ServiceMethod.ReturnType;
                    MethodInfo miSync = methodInfo.MakeGenericMethod(new Type[] { resultTypeSync });
                    Task task = miSync.Invoke(httpclientPart, new object[] { default }) as Task;
                    await task.ConfigureAwait(false);
                    PropertyInfo resultProperty = task.GetType().GetProperty("Result");
                    context.ReturnValue = resultProperty.GetValue(task);
                    return;
                }
                Type resultTypeAsync = context.ServiceMethod.ReturnType.GetGenericArguments()[0];
                MethodInfo miAsync = methodInfo.MakeGenericMethod(new Type[] { resultTypeAsync });
                context.ReturnValue = miAsync.Invoke(httpclientPart, new object[] { default });
            }
            catch (Exception ex)
            {
                context.ServiceProvider.GetService<ILogger<HttpServiceBusProxy>>().LogError(ex, "远程调用发生异常");
                throw;
            }
        }



       


    }
}
